#include <sys/types.h> 
#include <sys/stat.h> 
#include <string.h> 
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h> 
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <assert.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <linux/types.h>
#include "cetc14-iic.h"

int higher2lower(char c);
int htoi(char s[]);


#define CREAT_MASK(start,end) (~(0xffffffff << (start - end + 1)) << end)

int main(int argc, char *argv[]) 
{
	unsigned int tempval,tempval1;
	int i,count;
	
	unsigned int port, level, group;

	unsigned int reg_address;
	unsigned int value;
	unsigned int tx_pkt_cnt,tx_retry_cnt,rx_pkt_cnt,rx_retry_cnt,tx_pna_cnt,rx_pna_cnt;
	unsigned int sdi_index;

	count = 0;
	tempval = 0;
	tempval1 = 0;
	port = htoi(argv[1]);
	sdi_index=htoi(argv[2]);

	reg_address = 0x1C110 + 0x100 * port + 0x4 * 0;
//	printf("address is %#x, port is %#x\n",reg_address,port);
	value = 0xFF80;
	iic_access(sdi_index,0x58,reg_address,&value,0);
	reg_address = 0x1C110 + 0x100 * port + 0x4 * 1;
	value = 0xFF00;
	iic_access(sdi_index,0x58,reg_address,&value,0);

	reg_address = 0x1C110 + 0x100 * port + 0x4 * 2;
	value = 0xFF88;
	iic_access(sdi_index,0x58,reg_address,&value,0);

	reg_address = 0x1C110 + 0x100 * port + 0x4 * 3;
	value = 0xFF08;
	iic_access(sdi_index,0x58,reg_address,&value,0);

	reg_address = 0x1C110 + 0x100 * port + 0x4 * 4;
	value = 0xFF89;
	iic_access(sdi_index,0x58,reg_address,&value,0);
	reg_address = 0x1C110 + 0x100 * port + 0x4 * 5;
	value = 0xFF09;
	iic_access(sdi_index,0x58,reg_address,&value,0);
	reg_address = 0x1C110 + 0x100 * port + 0x4 * 6;
	value = 0xFF81;
	iic_access(sdi_index,0x58,reg_address,&value,0);
	reg_address = 0x1C110 + 0x100 * port + 0x4 * 7;
	value = 0xFF01;
	iic_access(sdi_index,0x58,reg_address,&value,0);

	reg_address = 0x1C100 + 0x100 * port;
	value = 0x80000000;
	iic_access(sdi_index,0x58,reg_address,&value,0);
	printf("Port %d Counter:\n",port);

	reg_address = 0x1c130 + 0x100 * port + 0x4 * 0;
	iic_access(sdi_index,0x58,reg_address,&tx_pkt_cnt,1);
	printf("Tx_Pkt_cnt    :%#x\n",tx_pkt_cnt);

	reg_address = 0x1c130 + 0x100 * port + 0x4 * 1;
	iic_access(sdi_index,0x58,reg_address,&rx_pkt_cnt,1);
	printf("Rx_Pkt_cnt    :%#x\n",rx_pkt_cnt);

	reg_address = 0x1c130 + 0x100 * port + 0x4 * 2;
	iic_access(sdi_index,0x58,reg_address,&tx_retry_cnt,1);
	printf("Tx_Retry_cnt  :%#x\n",tx_retry_cnt);

	reg_address = 0x1c130 + 0x100 * port + 0x4 * 3;
	iic_access(sdi_index,0x58,reg_address,&rx_retry_cnt,1);
	printf("Rx_Retry_cnt  :%#x\n",rx_retry_cnt);

	reg_address = 0x1c130 + 0x100 * port + 0x4 * 4;
	iic_access(sdi_index,0x58,reg_address,&tx_pna_cnt,1);
	printf("Tx_PNA_cnt    :%#x\n",tx_pna_cnt);

	reg_address = 0x1c130 + 0x100 * port + 0x4 * 5;
	iic_access(sdi_index,0x58,reg_address,&rx_pna_cnt,1);
	printf("Rx_PNA_cnt    :%#x\n",rx_pna_cnt);

	reg_address = 0x1c130 + 0x100 * port + 0x4 * 6;
	iic_access(sdi_index,0x58,reg_address,&tempval,1);
	printf("Tx_SWpkt_cnt  :%#x\n",tempval);
	reg_address = 0x1c130 + 0x100 * port + 0x4 * 7;
	iic_access(sdi_index,0x58,reg_address,&tempval,1);
	printf("Rx_SWpkt_cnt  :%#x\n",tempval);
	if((tx_pkt_cnt + tx_retry_cnt) == (rx_pkt_cnt + rx_retry_cnt))
	{
		printf("PKT_Result:Tx = Rx\n");
	}
	else
	{
		printf("PKT_Result:Tx != Rx\n");
	}

	if(tx_pna_cnt != 0 || rx_pna_cnt != 0)
	{
		printf("Error: PKT_PNA_cnt is NOT 0\n");
	}

	value = port;
	printf("port %d Counter\n",value);
	reg_address = 0x241780 + 0x4 * value;
	iic_access(sdi_index,0x58,reg_address,&tempval,1);
	printf("Rx_Switch_cnt  :%#x\n",tempval);

	reg_address = 0x241880 + 0x4 * value;
	iic_access(sdi_index,0x58,reg_address,&tempval,1);
	printf("Tx_Switch_cnt  :%#x\n",tempval);

	reg_address = 0x241700 + 0x4 * value;
	iic_access(sdi_index,0x58,reg_address,&tempval,1);
	printf("Ob_Drop_cnt  :%#x\n",tempval);

	reg_address = 0x241800 + 0x4 * value;
	iic_access(sdi_index,0x58,reg_address,&tempval,1);
	printf("sw_rx_pkt_err_cnt  :%#x\n",tempval);

	reg_address = 0x241900 + 0x4 * value;
	iic_access(sdi_index,0x58,reg_address,&tempval,1);
	printf("sw_rx_pkt_Drop_cnt  :%#x\n",tempval);
	return 0;
}

int higher2lower(char c)
{
	if(c >= 'A' && c <= 'Z')
		return c + 'a' - 'A';
	else
	  return c;
}

int htoi(char s[])
{
	int i;
	int n = 0;
	if(s[0] == '0' && (s[1] == 'x' || s[1] == 'x'))
	  i = 2;
	else
	  i = 0;
	for(;(s[i] >= '0' && s[i] <= '9') || (s[i] >= 'a' && s[i] <= 'f') \
			|| (s[i] >= 'A' && s[i] <= 'F'); ++i)
	{
		if(higher2lower(s[i] > '9'))
		{
			n = 16 * n +(10 + higher2lower(s[i]) - 'a');
		}
		else
		  n = 16 * n + (higher2lower(s[i] - '0'));
	}
	return n;
}
